﻿using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace Resn.WhuPub.BLL
{
        /// <summary>
        /// 智能查询条件
        /// </summary>
        /// <typeparam name="T">查询数据的类型</typeparam>
        public class QueryCondition<T>
        {
                #region 构造函数
                /// <summary>
                /// 初始化智能查询条件
                /// </summary>
                /// <param name="queryName">查询的列名</param>
                /// <param name="compareType">查询的比较方式</param>
                /// <param name="queryValue">查询的比较值</param>
                public QueryCondition(string queryName, CompareType compareType, Object queryValue)
                {
                        QueryName = queryName;

                        ClassType = typeof(T);
                        PropertyInfo pi = (ClassType.GetProperties().Where(i =>
                                {
                                        var queryAttribute = Attribute.GetCustomAttribute(i, typeof (QueryAttribute)) as QueryAttribute;
                                        return queryAttribute != null && queryAttribute.Name == QueryName;
                                })).First();

                        PropertyName = pi.Name;
                        QueryValue = queryValue;
                        CompareType = compareType;
                } 
                #endregion

                #region 属性
                /// <summary>
                /// 获取查询数据的类型
                /// </summary>
                /// <value>
                /// 查询数据的类型
                /// </value>
                private Type ClassType { get; set; }

                /// <summary>
                /// 获取查询数据的特性名称
                /// </summary>
                /// <value>
                /// 查询数据的特性名称
                /// </value>
                private String QueryName { get; set; }

                /// <summary>
                /// 获取查询数据的属性名称
                /// </summary>
                /// <value>
                /// 查询数据的属性名称
                /// </value>
                private String PropertyName { get; set; }

                /// <summary>
                /// 获取或设置查询数据的查询值
                /// </summary>
                /// <value>
                /// 查询数据的查询值
                /// </value>
                private Object QueryValue { get; set; }

                /// <summary>
                /// 获取查询数据的比较类型
                /// </summary>
                /// <value>
                /// 查询数据的比较类型
                /// </value>
                private CompareType CompareType { get; set; } 
                #endregion

                #region 方法
                /// <summary>
                /// 生成查询条件的代理
                /// </summary>
                /// <returns>由查询条件产生的Lambda表达式生成的代理</returns>
                public Func<T, bool> GenerateLambdaDelegate()
                {
                        //表示二元运算符的左边参数名称
                        ParameterExpression parameter = Expression.Parameter(ClassType, "item");

                        //表示"stu"参数的"stu.Name"中的Name属性，Name属性必须是反射获取的元数据才行，这样框架就才可以找到它
                        PropertyInfo propertyInfo = ClassType.GetProperty(PropertyName);
                        MemberExpression property = Expression.MakeMemberAccess(parameter, propertyInfo);

                        //比较值
                        ConstantExpression rightValue = Expression.Constant(Convert.ChangeType(QueryValue, propertyInfo.PropertyType));

                        //拼接==运算符的左边、右边
                        BinaryExpression binary = Expression.MakeBinary(CompareType.ConvertToExpressionType(), property, rightValue);

                        //生成Lambda表达式
                        LambdaExpression lambda = Expression.Lambda(binary, parameter);

                        //Lambda表达式转为可执行的委托
                        return lambda.Compile() as Func<T, bool>;
                } 
                #endregion
        }
}